# -*- coding: utf-8 -*-
"""
Gitee Release 无感更新器（保留接口：do_update() -> bool）
"""
import os
import sys
import shutil
import subprocess
import traceback
from pathlib import Path
import requests
import time
from utils.constants import VERSION as LOCAL_VERSION

from utils.constants import UPDATE_CONFIG as CFG

def check_update(): #检查更新
    """返回 (need, release_dict)"""
    try:
        rsp = requests.get(	CFG["API_URL"], timeout=10)
        rsp.raise_for_status()
        rel = rsp.json()
        latest = rel["tag_name"].lstrip("v")
        print(f"[UPD] 本地版本: {LOCAL_VERSION}")
        print(f"[UPD] 远程版本: {latest}")
        if latest > LOCAL_VERSION:
            return True, rel
        return False, None
    except Exception as e:
        print(f"[UPD] 检查更新失败: {e}")
        return False, None

def do_update() -> bool: #执行更新(主入口)
    """唯一外部入口：check→download→build vbs→pop wscript;主入口：检查->下载->启动升级器->返回 True 表示已启动升级"""

    # 添加更新锁文件，防止重复更新
    update_lock = Path(CFG["UPDATE_LOCK"])
    if update_lock.exists():
        # 检查锁文件时间，如果超过10分钟则删除
        lock_time = update_lock.stat().st_mtime
        if time.time() - lock_time > 600:
            update_lock.unlink(missing_ok=True)
        else:
            print("[UPD] 检测到正在进行的更新，跳过")
            return False
    
    try:
        update_lock.touch(exist_ok=True)
        
        need, rel = check_update()
        if not need:
            update_lock.unlink(missing_ok=True)
            return False
            
        zip_path = download_asset(rel)
        vbs_file = unpack_and_apply(zip_path, rel["tag_name"].lstrip("v"))

        # 方案 B：用绝对路径启动 wscript.exe
        import os
        wscript = os.path.join(
            os.environ.get('SystemRoot', r'C:\Windows'),
            'System32',
            'wscript.exe'
        )
        subprocess.Popen([wscript, '//B', vbs_file], cwd=Path.cwd())

        return True
    except Exception:
        traceback.print_exc()
        # 清理失败残留 - 添加安全的清理逻辑
        items_to_clean = [
            CFG["UPDATE_TMP_ZIP"], 
            CFG["UPDATE_UNZIP_DIR"], 
            CFG["UPDATE_HELPER"], 
            CFG["UPDATE_LOCK"], 
            "timetracker-repo",
            "git_config.json"  # 也可以选择清理配置文件
        ]
        
        for item in items_to_clean:
            try:
                path_obj = Path(item)
                if path_obj.exists():
                    if path_obj.is_file():
                        path_obj.unlink(missing_ok=True)
                        print(f"[UPD] 已清理文件: {item}")
                    elif path_obj.is_dir():
                        shutil.rmtree(path_obj, ignore_errors=True)
                        print(f"[UPD] 已清理目录: {item}")
                else:
                    print(f"[UPD] 无需清理: {item} 不存在")
            except Exception as e:
                print(f"[UPD] 清理 {item} 失败: {e}")
        return False
    finally:
        update_lock.unlink(missing_ok=True)

def download_asset(rel: dict) -> Path: #下载更新包
    """下载 zip 资产，返回临时路径"""

    zip_url = next((a["browser_download_url"] for a in rel["assets"]
                   if a["name"].endswith(".zip")), None)
    if not zip_url:
        raise RuntimeError("Release 里没有 .zip 资产")
    tmp = Path(CFG["UPDATE_TMP_ZIP"])
    print(f"[UPD] 开始下载 {zip_url}")
    with requests.get(zip_url, stream=True, timeout=30) as r:
        r.raise_for_status()
        with tmp.open("wb") as f:
            for chunk in r.iter_content(chunk_size=8192):
                f.write(chunk)
    print(f"[UPD] 下载完成 {tmp.stat().st_size} 字节")
    return tmp

def _build_vbs(unzip_dir: Path, new_ver: str) -> Path: #生成自删除 VBS 脚本
    '''生成自删除 VBS 脚本，负责杀进程→覆盖→重启'''

    vbs = Path(CFG["UPDATE_HELPER"])
    exe_name = "Tracker.exe"
    current_dir = r"D:\Tracker_Data"
    exe_path    = rf"{current_dir}\{exe_name}"
    log_path    = rf"{current_dir}\vbs_run.log"

    vbs_content = f'''

On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
Set wsh = CreateObject("WScript.Shell")

Sub LogIt(msg)
    With fso.OpenTextFile("{log_path}", 8, True)
        .WriteLine Now & "  " & msg
    End With
End Sub

LogIt "VBS 开始执行"

Set wmi = GetObject("winmgmts:\\\\.\\root\\cimv2")
For attempt = 1 To 10
    killed = 0
    Set procs = wmi.ExecQuery("SELECT * FROM Win32_Process WHERE Name='{exe_name}'")
    For Each p In procs
        p.Terminate()
        killed = killed + 1
    Next
    LogIt "第" & attempt & "轮，杀死进程数=" & killed
    If killed = 0 Then Exit For
    wsh.Sleep 1000
Next

wsh.Sleep 3000

If Not fso.FolderExists("{unzip_dir}") Then
    LogIt "解压目录不存在：{unzip_dir}"
    WScript.Quit 1
End If

For Each f In fso.GetFolder("{unzip_dir}").Files
    src = f.Path
    dst = fso.BuildPath("{current_dir}", f.Name)
    If fso.FileExists(dst) Then
        If LCase(f.Name) = LCase("{exe_name}") Then
            back = dst & ".old"
            If fso.FileExists(back) Then fso.DeleteFile back, True
            fso.MoveFile dst, back
            LogIt "重命名旧exe → " & back
        Else
            fso.DeleteFile dst, True
        End If
    End If
    fso.MoveFile src, dst
    LogIt "移动 " & f.Name & " → " & dst
Next

Set verFile = fso.CreateTextFile("{current_dir}\\version.txt", True)
verFile.Write "{new_ver}"
verFile.Close
LogIt "版本号已写入 " & "{new_ver}"

fso.DeleteFile "{current_dir}\\update_tmp.zip", True
fso.DeleteFolder "{current_dir}\\update_unzip", True
LogIt "临时文件已清理"

' ===== 启动新 exe =====
newExe = "D:\Tracker_Data\Tracker.exe"
If fso.FileExists(newExe) Then
    wsh.CurrentDirectory = "D:\Tracker_Data"
    ' 老引擎兼容写法：Shell 同步启动
    exitCode = wsh.Popup("正在启动新版本...", 1, "升级器", 64)  ' 仅提示，可删
    Dim shellApp
    Set shellApp = CreateObject("Shell.Application")
    shellApp.ShellExecute newExe, "", "", "open", 1
    ' ShellExecute 不返回退出码，老版本只能放弃退出码
    LogIt "已启动新exe（同步等待模式已放弃）"
Else
    LogIt "新exe不存在！路径=" & newExe
End If

WScript.Sleep 5000   ' 5 秒
fso.DeleteFile WScript.ScriptFullName, True
'''
    with vbs.open("w", encoding="gbk") as f:
        f.write(vbs_content)
    return vbs

def unpack_and_apply(zip_path: Path, new_ver: str) -> Path: #解压到 update_unzip
    """解压并准备更新，返回 VBS 脚本路径"""
    
    unzip_dir = Path(CFG["UPDATE_UNZIP_DIR"])
    shutil.rmtree(unzip_dir, ignore_errors=True)
    unzip_dir.mkdir()
    shutil.unpack_archive(str(zip_path), str(unzip_dir), "zip")
    return _build_vbs(unzip_dir, new_ver)

if __name__ == "__main__":
    ok = do_update()
    # sys.exit(0 if ok else 1)   # 禁止杀进程